package com.sojson.config.filter;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.filter.OncePerRequestFilter;

import com.alibaba.fastjson.JSONObject;
import com.sojson.config.filter.interfaces.SignatureVerificationFilterInterface;
import com.sojson.util.StringUtil;
import com.sojson.util.encryption.EncryptionUtil;
import com.sojson.util.filter.FilterUtil;
import com.sojson.util.json.JsonUtil;

/**
 * 签名验证过滤器(先解密在验证)
 * 
 * @author liu
 * @date 2020-11-02
 */
public class SignatureVerificationDecryptionFilter extends OncePerRequestFilter
    implements SignatureVerificationFilterInterface {

    /** 不过滤的路径 */
    private HashSet<String> excludePath;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws ServletException, IOException {

        if (isExcludePath(excludePath)) {
            chain.doFilter(request, response);
            return;
        }

        HttpServletRequest httpRequest = request;
        try {
            String header = httpRequest.getHeader(SIGNATURE_NAME);
            if (isBlankObject(header)) {
                return;
            }

            // 解密
            JSONObject parseObject =
                jsonToObject(decryption(header, SignatureVerificationFilterInterface.SIGNATURE_KEY), JSONObject.class);
            // 传过来的时间戳
            Long date = parseObject.getLong(SIGNATURE_DATE);
            // 如果为空就结束
            if (isBlankObject(date)) {
                return;
            }
            // 当前系统时间戳
            long currentTimeMillis = System.currentTimeMillis();
            // 如果传过来的时间戳大于当前系统时间戳或者比范围内要小就拦截
            if (date > currentTimeMillis || date < currentTimeMillis - SIGNATURE_DATE_SCOPE) {
                return;
            }
            // 遍历所有要验证的签名
            Set<String> keySet = SIGNATURE_VALUE.keySet();
            for (String string : keySet) {
                if (!SIGNATURE_VALUE.get(string).equals(parseObject.getString(string))) {
                    return;
                }
            }
        } catch (Exception e) {
            return;
        }

        chain.doFilter(request, response);
    }

    /**
     * 判断一个对象是否是空(空对象)
     * 
     * @param obj
     * @return
     */
    private boolean isBlankObject(Object obj) {
        return StringUtil.isBlankObject(obj);
    }

    /**
     * 判断当前路径是否不过滤(过滤器无法设置不过滤哪些路径,要自己做)
     * 
     * @return
     */
    private boolean isExcludePath(HashSet<String> excludePath) {
        return FilterUtil.isExcludePath(excludePath);
    }

    /**
     * 解密方法
     * 
     * @param inStr
     * @param key 解密密钥
     * @return
     */
    private String decryption(String inStr, String key) {
        return EncryptionUtil.decryption(inStr, key);
    }

    /**
     * 将json字符串转换成对象
     * 
     * @param jsonData json字符串
     * @param beanType 要转换成的对象的类型
     * @return 得到的对象
     */
    private <T> T jsonToObject(String jsonData, Class<T> beanType) {
        return JsonUtil.jsonToObject(jsonData, beanType);
    }

    /**
     * 获取不过滤的路径
     * 
     * @return
     */
    @Override
    public HashSet<String> getExcludePath() {
        return this.excludePath;
    }

    /**
     * 设置不过滤的路径
     * 
     * @param excludePath
     */
    @Override
    public void setExcludePath(HashSet<String> excludePath) {
        this.excludePath = excludePath;
    }

    /**
     * 获取当前过滤器的名字
     */
    @Override
    public String getName() {
        String name = "signaVeria";
        return name;
    }

}